package tools

import (
	"encoding/csv"
	"encoding/json"
	"fmt"
	"io"
	"os"
	"strings"
	"uni-core/globals"
	"uni-core/pkg/cryptokey"

	"github.com/jmoiron/sqlx"
)

// ExportToCSV 函数
func ExportToCSV(data globals.PswdDatas, writer io.Writer, decrypt bool) error {
	// 创建 CSV 写入器
	csvWriter := csv.NewWriter(writer)
	defer csvWriter.Flush()

	// 定义CSV头部
	headers := []string{"title", "username", "password", "link", "description"}
	if err := csvWriter.Write(headers); err != nil {
		return err
	}

	// 遍历数据并写入CSV
	for _, item := range data {
		var row []string
		var decodeErr error

		// 处理密码字段
		password := item.Password

		// 根据返回的decrypt参数, 进行处理, true: 解密, false: 不处理(加密)
		if decrypt {
			password, decodeErr = cryptokey.DecodeBase64(password)
			if decodeErr != nil {
				password = "解密失败"
			}
		}

		// 构建行数据
		row = append(row, item.Title)
		row = append(row, item.Username)
		row = append(row, password)
		row = append(row, item.Link)
		row = append(row, item.Description)

		if err := csvWriter.Write(row); err != nil {
			return err
		}
	}
	return nil
}

// ImportFromCSVPwsdData pwsd_data表的导入函数
func ImportFromCSVPwsdData(filePath string, db *sqlx.DB, count *int) error {
	// 打开 CSV 文件
	file, err := os.Open(filePath)
	if err != nil {
		return fmt.Errorf("打开文件时发生了错误: %s", err)
	}
	defer file.Close()

	// 创建 CSV 读取器
	csvReader := csv.NewReader(file)
	records, err := csvReader.ReadAll()
	if err != nil {
		return fmt.Errorf("读取 CSV 文件时发生了错误: %s", err)
	}

	// 构造插入SQL语句
	insertSQL := "INSERT INTO pswd_data (title, username, password, link, description) VALUES (?, ?, ?, ?, ?)"

	// 遍历导入的数据，并插入到数据库中
	for _, record := range records {
		// 跳过空行
		if len(record) == 0 {
			continue
		}

		// 跳过表头
		if record[0] == "title" || record[0] == "username" || record[0] == "password" || record[0] == "link" || record[0] == "description" {
			continue
		}

		// 校验必需字段
		if len(record) < 3 || record[0] == "" || record[1] == "" || record[2] == "" {
			return fmt.Errorf("数据格式错误: 必须包含标题、用户名和密码字段")
		}

		// 执行插入操作
		password := record[2]
		// 检查密码字段, 如果不是以ExportDataPrefix开头, 则进行加密处理
		if !strings.HasPrefix(password, globals.ExportDataPrefix) {
			password = cryptokey.EncodeBase64(password)
		}

		// 执行插入操作
		if _, err := db.Exec(insertSQL, record[0], record[1], password, record[3], record[4]); err != nil {
			return fmt.Errorf("导入数据时发生了错误: %s", err)
		}

		// 递增计数器
		*count++
	}

	return nil
}

// ExportToJSON 导出数据为JSON格式
func ExportToJSON(data globals.PswdDatas, writer io.Writer, decrypt bool) error {
	// 将数据编码为JSON格式
	encoder := json.NewEncoder(writer)
	encoder.SetIndent("", "  ")

	// 根据decrypt参数, 进行处理, true: 解密, false: 不处理(加密)
	if decrypt {
		// 直接操作PswdDatas结构体的Password字段
		for i := range data {
			var decodeErr error
			data[i].Password, decodeErr = cryptokey.DecodeBase64(data[i].Password)
			if decodeErr != nil {
				data[i].Password = "解密失败" // 替换为错误信息
			}
		}
	}
	// 将数据编码为JSON格式
	if err := encoder.Encode(data); err != nil {
		return fmt.Errorf("JSON编码时发生了错误: %s", err)
	}
	return nil
}

// ImportFromJSONPwsdData 从JSON文件导入数据到pswd_data表
func ImportFromJSONPwsdData(filePath string, db *sqlx.DB, count *int) error {
	// 打开JSON文件
	file, err := os.Open(filePath)
	if err != nil {
		return fmt.Errorf("打开文件时发生了错误: %s", err)
	}
	defer file.Close()

	// 解码JSON数据
	var records []map[string]interface{}
	decoder := json.NewDecoder(file)
	if err := decoder.Decode(&records); err != nil {
		return fmt.Errorf("解析JSON数据时发生了错误: %s", err)
	}

	// 构造插入SQL语句
	insertSQL := "INSERT INTO pswd_data (title, username, password, link, description) VALUES (?, ?, ?, ?, ?)"

	// 遍历导入的数据，并插入到数据库中
	for _, record := range records {
		// 校验必需字段
		if _, ok := record["title"]; !ok {
			return fmt.Errorf("数据格式错误: 缺少标题字段")
		}
		if _, ok := record["username"]; !ok {
			return fmt.Errorf("数据格式错误: 缺少用户名字段")
		}
		if _, ok := record["password"]; !ok {
			return fmt.Errorf("数据格式错误: 缺少密码字段")
		}
		if record["title"] == "" || record["username"] == "" || record["password"] == "" {
			return fmt.Errorf("数据格式错误: 标题、用户名和密码不能为空")
		}

		// 执行插入操作
		password := record["password"]
		// 检查密码字段, 如果不是以ExportDataPrefix开头, 则进行加密处理
		if !strings.HasPrefix(password.(string), globals.ExportDataPrefix) {
			password = cryptokey.EncodeBase64(password.(string))
		}

		if _, err := db.Exec(insertSQL,
			record["title"],
			record["username"],
			password,
			record["link"],
			record["description"]); err != nil {
			return fmt.Errorf("导入数据时发生了错误: %s", err)
		}

		// 递增计数器
		*count++
	}

	return nil
}
